/** @name 字典缓存处理（setDict 后数据不可变） */
import { getDictByCode } from '@/api/modules/dict'
import { deepFreeze } from '@/utils/util'
/** @description 状态枚举 */
enum Status {
	/** @description 请求中 */
	PADDING,
	/** @description 成功 */
	FUlFILLED,
	/** @description 失败 */
	REJECTED
}

interface DictItem {
	status: Status
	value: any[]
	callbacks: Function[]
	/** @description 这个字典失败时的时间，避免失败多次调用 */
	errorTimestamp: number
}
interface DictContent {
	[key: string]: DictItem
}
export class DictContextHolder {
	// 调用接口返回的动态字典
	protected dict: DictContent = {}
	/**
	 * @description 获取字典
	 * @param dictCode
	 * @param forceReq
	 * @returns
	 */
	getDict(dictCode: string, forceReq: boolean = false): Promise<Array<any>> {
		return new Promise(resolve => {
			if (forceReq) {
				this.setDict(dictCode, [])
			}

			let dictInfo = this.dict[dictCode]
			if (dictInfo) {
				switch (dictInfo.status) {
					case Status.PADDING:
						// 正在请求中
						dictInfo.callbacks.push(resolve)
						return
					case Status.FUlFILLED:
						// 已请求成功结果
						resolve(dictInfo.value)
						return
					default:
						// 已有请求失败结果
						if (dictInfo.errorTimestamp) {
							const currentTime = new Date().getTime()
							if (currentTime - dictInfo.errorTimestamp <= 5000) {
								// 避免失败多次调用，两次失败间隔在5秒内，则刷新时间戳，并直接返回结果
								dictInfo.errorTimestamp = currentTime
								resolve(dictInfo.value)
								return
							}
						}
						break
				}
			}

			dictInfo = this.dict[dictCode] = {
				status: Status.PADDING,
				callbacks: [resolve],
				value: [],
				errorTimestamp: 0
			}
			getDictByCode(dictCode)
				.then((res: any) => {
					this.dict[dictCode].status = Status.FUlFILLED
					this.dict[dictCode].value = res
					dictInfo.callbacks.forEach((cb: Function) => {
						cb(res)
					})
				})
				.catch((e: Error) => {
					this.dict[dictCode].status = Status.REJECTED
					this.dict[dictCode].errorTimestamp = new Date().getTime()
					this.dict[dictCode].value = []
					dictInfo.callbacks.forEach((cb: Function) => {
						cb([])
					})
					throw e
				})
		})
	}

	/**
	 * @description 设置字典
	 * @param dictCode
	 * @param dictList
	 */
	setDict(dictCode: string, dictList: any[]): void {
		// 深度冻结，让数据不可变
		deepFreeze(dictList)
		this.dict[dictCode] = {
			status: Status.FUlFILLED,
			callbacks: [],
			value: dictList,
			errorTimestamp: 0
		}
	}

	/**
	 *  @description 清空所有字典缓存
	 */
	clearDictCache(): void {
		this.dict = {}
	}
}

export default new DictContextHolder()
